import java.io.*;
import java.util.Scanner;
import javax.swing.JFrame;

/**
 * Main class to run the simulator.
 * CS 149 Project, Phase 1
 * @author Timmy Yee
 */

public class Simulator
{
    // set GUI parameters
    public static final String TITLE = "Operating System Simulator";
    public static final int POS_X = 100;
    public static final int POS_Y = 100;
    public static final int WIDTH = 640;
    public static final int HEIGHT = 480;
    public static final double TIME_UNIT = 0.1;

    private static double currentTime;
    private static Display gui;

    /**
     * Creates the frame for the simulator window.
     */
    private static void createFrame()
    {
        JFrame frame = new JFrame();
        frame.setTitle(TITLE);
        frame.setBounds(POS_X, POS_Y, WIDTH, HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        gui = new Display(frame);
        frame.add(gui);
        frame.setVisible(true);
    }

    /**
     * Prints the header for the trace.
     */
    private static void printHeader()
    {
        gui.append("\t\t\tTrace\n\n");
        gui.append("Scheduling: " + Scheduler.getAlgorithmName() + "\n");
        gui.append("Time slice:\t\t" + Processor.getTimeSlice() + " msec\n");
        gui.append("Context switching:\t" +
                   Processor.getContextSwitch() + " msec\n");
        gui.append("Display queues every:\t" +
                   Processor.getDisplayInterval() + " msec\n");
        gui.append("Pause at:\t\t" +
                   Processor.getPauseInterval() + " msec\n\n");
        gui.append("Time\tEvent\n");
        gui.append("(msec)\n");
        gui.append("---\t------\n");
    }

    /**
     * Gets the statistics for the simulation.
     */
    private static void doStats()
    {
        gui.updateTurnaroundField(Scheduler.getAvgTurnaround());
        gui.updateWaitingField(Scheduler.getAvgWaiting());
        gui.updateResponseField(Scheduler.getAvgResponse());
    }

    /**
     * Main loop for simulation.
     */
    private static void loop()
    {
        printHeader();

        currentTime = 0;
        while (Scheduler.areProcessesActive()) {
            Processor.handleInterrupts(currentTime, gui);
            Scheduler.checkForNewArrival(currentTime, gui);
            Scheduler.activate(currentTime, gui);
            currentTime += TIME_UNIT;
        }

        doStats();
    }

    /**
     * Reads in test data for simulation.
     * @param file - file containing test data
     */
    public static void readTestData(File file)
    {
        Scanner test;
        Scheduler.initQueues();

        try {
            test = new Scanner(file);
        } catch (Exception e) {
            return;
        }

        while (test.hasNext())
            Scheduler.addNew(new Process(
                test.nextInt(), test.nextDouble(), test.nextDouble(),
                test.nextDouble(), test.nextDouble(), test.nextDouble(),
                test.nextDouble(), test.nextInt()
            ));

        loop();
    }

    public static void main(String[] args)
    {
        createFrame();
    }
}

